{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "source": [
    "import cv2\r\n",
    "import numpy as np"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 图像梯度-Sobel算子\r\n",
    "\r\n",
    "$ G_x = \\begin{bmatrix} -1 & 0 & 1 \\\\ -2 & 0 & 2 \\\\ -1 & 0 & 1 \\end{bmatrix} \\times A $ and $ G_y = \\begin{bmatrix} -1 & -2 & -1 \\\\ 0 & 0 & 0 \\\\ 1 & 2 & 1 \\end{bmatrix} \\times A $"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "source": [
    "img = cv2.imread('./pie.png', cv2.IMREAD_GRAYSCALE)\r\n",
    "cv2.imshow('img', img)\r\n",
    "cv2.waitKey()\r\n",
    "cv2.destroyAllWindows()"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "```python\r\n",
    "dst = cv2.Sobel(src, ddepth, dx, dy, ksize)\r\n",
    "```\r\n",
    "\r\n",
    "- `ddepth`: 图像的深度\r\n",
    "- `dx`和`dy`分别表示水平和竖直方向\r\n",
    "- `ksize`是Sobel算子的大小"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "source": [
    "def cv_show(name: str, img: np.ndarray) -> None:\r\n",
    "    cv2.imshow(name, img)\r\n",
    "    cv2.waitKey(0)\r\n",
    "    cv2.destroyAllWindows()"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "source": [
    "sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)\r\n",
    "\r\n",
    "cv_show('sobelx', sobelx)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "> `x`方向梯度，右-左\r\n",
    "\r\n",
    "白到黑是正数，黑到白是负数，负数截断成0。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "source": [
    "sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)\r\n",
    "sobelx = cv2.convertScaleAbs(sobelx)\r\n",
    "cv_show('sobelx', sobelx)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "source": [
    "sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)\r\n",
    "sobely = cv2.convertScaleAbs(sobely)\r\n",
    "cv_show('sobely', sobely)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "$ G = \\frac{1}{2} \\times ( \\lvert G_x \\rvert + \\lvert G_y \\rvert ) $"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "source": [
    "sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)\r\n",
    "cv_show('sobelxy', sobelxy)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "source": [
    "# 直接计算，效果不好\r\n",
    "sobelxy = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=3)\r\n",
    "sobelxy = cv2.convertScaleAbs(sobelxy)\r\n",
    "cv_show('sobelxy', sobelxy)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "source": [
    "img = cv2.imread('./lena.jpg', cv2.IMREAD_GRAYSCALE)\r\n",
    "\r\n",
    "sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)\r\n",
    "sobelx = cv2.convertScaleAbs(sobelx)\r\n",
    "sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)\r\n",
    "sobely = cv2.convertScaleAbs(sobely)\r\n",
    "sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)\r\n",
    "\r\n",
    "cv_show('sobelxy', sobelxy)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "source": [
    "img = cv2.imread('./lena.jpg', cv2.IMREAD_GRAYSCALE)\r\n",
    "\r\n",
    "sobelxy = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=3)\r\n",
    "sobelxy = cv2.convertScaleAbs(sobelxy)\r\n",
    "\r\n",
    "cv_show('sobelxy', sobelxy)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "# 图像梯度-Scharr算子\r\n",
    "\r\n",
    "$ G_x = \\begin{bmatrix} -3 & 0 & 3 \\\\ -10 & 0 & 10 \\\\ -3 & 0 & 3 \\end{bmatrix} \\times A $ and $ G_y = \\begin{bmatrix} -3 & 10 & 3 \\\\ 0 & 0 & 0 \\\\ 3 & 10 & 3 \\end{bmatrix} $"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 图像梯度-laplacian算子\r\n",
    "\r\n",
    "$ G = \\begin{bmatrix} 0 & 1 & 0 \\\\ 1 & -4 & 1 \\\\ 0 & 1 & 0 \\end{bmatrix} $"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "source": [
    "# 不同算子的差异\r\n",
    "img = cv2.imread('./lena.jpg', cv2.IMREAD_GRAYSCALE)\r\n",
    "\r\n",
    "sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)\r\n",
    "sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)\r\n",
    "sobelx = cv2.convertScaleAbs(sobelx)\r\n",
    "sobely = cv2.convertScaleAbs(sobely)\r\n",
    "sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)\r\n",
    "\r\n",
    "scharrx = cv2.Scharr(img, cv2.CV_64F, 1, 0)\r\n",
    "scharry = cv2.Scharr(img, cv2.CV_64F, 0, 1)\r\n",
    "scharrx = cv2.convertScaleAbs(scharrx)\r\n",
    "scharry = cv2.convertScaleAbs(scharry)\r\n",
    "scharrxy = cv2.addWeighted(scharrx, 0.5, scharry, 0.5, 0)\r\n",
    "\r\n",
    "laplacian = cv2.Laplacian(img, cv2.CV_64F)\r\n",
    "laplacian = cv2.convertScaleAbs(laplacian)\r\n",
    "\r\n",
    "res = np.hstack((sobelxy, scharrxy, laplacian))\r\n",
    "cv_show('res', res)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "source": [
    "# 不同算子的差异\r\n",
    "img = cv2.imread('./pie.png', cv2.IMREAD_GRAYSCALE)\r\n",
    "\r\n",
    "sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)\r\n",
    "sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)\r\n",
    "sobelx = cv2.convertScaleAbs(sobelx)\r\n",
    "sobely = cv2.convertScaleAbs(sobely)\r\n",
    "sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)\r\n",
    "\r\n",
    "scharrx = cv2.Scharr(img, cv2.CV_64F, 1, 0)\r\n",
    "scharry = cv2.Scharr(img, cv2.CV_64F, 0, 1)\r\n",
    "scharrx = cv2.convertScaleAbs(scharrx)\r\n",
    "scharry = cv2.convertScaleAbs(scharry)\r\n",
    "scharrxy = cv2.addWeighted(scharrx, 0.5, scharry, 0.5, 0)\r\n",
    "\r\n",
    "laplacian = cv2.Laplacian(img, cv2.CV_64F)\r\n",
    "laplacian = cv2.convertScaleAbs(laplacian)\r\n",
    "\r\n",
    "res = np.hstack((sobelxy, scharrxy, laplacian))\r\n",
    "cv_show('res', res)"
   ],
   "outputs": [],
   "metadata": {}
  }
 ],
 "metadata": {
  "orig_nbformat": 4,
  "language_info": {
   "name": "python",
   "version": "3.8.10",
   "mimetype": "text/x-python",
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "pygments_lexer": "ipython3",
   "nbconvert_exporter": "python",
   "file_extension": ".py"
  },
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3.8.10 64-bit ('.venv': pipenv)"
  },
  "interpreter": {
   "hash": "39f99c23feb409312b8721cf18cab0f26d8d66a36c9edd8d89bb6573c49dc130"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}